//
// Created by guqiao on 20-7-16.
// 动态注册
//

#include <jni.h>
#include <assert.h>

jstring callNativeMethod(JNIEnv *env, jobject thiz, jstring text) {
    jclass clazz = env->GetObjectClass(thiz);
    jmethodID methodId = env->GetMethodID(clazz,"callJavaMethod", "(Ljava/lang/String;)V");
    env->CallVoidMethod(thiz,methodId,text);
    return env->NewStringUTF("成功调用Java普通方法");
}

jstring staticCallNativeMethod(JNIEnv *env, jclass clazz, jstring text) {
    jmethodID methodId = env->GetStaticMethodID(clazz,"callStaticJavaMethod","(Ljava/lang/String;)V");
    env->CallStaticVoidMethod(clazz,methodId,text);
    return env->NewStringUTF("成功调用java静态方法");
}

void changeJavaField(JNIEnv *env, jobject thiz) {
    jclass clazz = env->GetObjectClass(thiz);
    jfieldID fieldId = env->GetFieldID(clazz,"name", "Ljava/lang/String;");
    jstring name = static_cast<jstring>(env->GetObjectField(thiz, fieldId));
    jstring newValue = env->NewStringUTF("我是新的属性值");
    env->SetObjectField(thiz,fieldId,newValue);
}

void changeJavaStaticField(JNIEnv *env, jobject thiz) {
    jclass clazz = env->GetObjectClass(thiz);
    jfieldID fieldId = env->GetStaticFieldID(clazz,"index", "I");
    jint value = env->GetStaticIntField(clazz,fieldId);
    jint newIndex = value + 10;
    env->SetStaticIntField(clazz,fieldId,newIndex);
}

static JNINativeMethod getMethods[] = {
        {"callNativeMethod","(Ljava/lang/String;)Ljava/lang/String;",(void *)callNativeMethod},
        {"staticCallNativeMethod","(Ljava/lang/String;)Ljava/lang/String;",(void *)staticCallNativeMethod},
        {"changeJavaField","()V",(void *)changeJavaField},
        {"changeJavaStaticField","()V",(void *)changeJavaStaticField},
};

static int registerNativeMethods(JNIEnv* env, const char* className,JNINativeMethod* getMethods,int methodsNum){
    jclass clazz;
    clazz = env->FindClass(className);
    if(clazz == NULL){
        return JNI_FALSE;
    }
    if(env->RegisterNatives(clazz,getMethods,methodsNum) < 0){
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

static int registerNatives(JNIEnv* env){
    const char* className = "com/guqiao/sdk/Sdk";
    return registerNativeMethods(env,className,getMethods, sizeof(getMethods)/ sizeof(getMethods[0]));
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM*vm,void*reserved) {
    JNIEnv *env = NULL;
    if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    assert(env != NULL);

    if (!registerNatives(env)) {
        return -1;
    }
    return JNI_VERSION_1_6;
}